/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package bsc.war.test;

import bsc.ejb.entity.Label;
import bsc.ejb.entity.Milestone;
import bsc.ejb.entity.MilestoneTracer;
import bsc.ejb.entity.Project;
import bsc.ejb.entity.Task;
import bsc.ejb.entity.Tracer;
import bsc.war.delegate.DelegateBSC;
import bsc.war.factory.Factory;
import bsc.war.model.DatesPojo;
import bsc.war.service.DatesUtil;
import bsc.war.service.ScoreCardUtils;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;

/**
 *
 * @author luisZavaleta
 */
public class XmlProject extends AbstractController {

    private final String DATE_FORMAT = "yyyy,M,d";
    private final SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
    private DelegateBSC delegate;

    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest request,
            HttpServletResponse response) throws Exception {

        ModelAndView mav = new ModelAndView();

        try {
            delegate = (DelegateBSC) Factory.getBean("DelegateBSC");

            // System.out.println("" + request.getParameter("idProject"));
            Long idProject = Long.parseLong(request.getParameter("idProject"));

            Project project = delegate.findProject(idProject);

            Task rootTask = delegate.findRootTask(project);

            List<Task> tasks = delegate.findTask(rootTask);// delegate.findMilestone(project); // new ArrayList<Task>();//rootTask.getTasks();
            // tasks.add(rootTask);

            Document doc = DocumentHelper.createDocument();

            Element superRoot = doc.addElement("root");
            doc.setXMLEncoding("ISO-8859-1");

            Element root = superRoot.addElement("projects");

            Element proj = root.addElement("project");
            proj.addAttribute("name", "" + removeLatinChars(project.getName()));

            proj.addAttribute("id", "P" + project.getIdScoreCard());

            DatesPojo projectDates = this.getDates(delegate, project);

            DatesPojo newDates = new DatesPojo();
            this.insertTasks(proj, tasks, newDates);

            proj.addAttribute("startdate", sdf.format(projectDates.getFirstDate()));

            XmlView xv = new XmlView(doc);
            response.setContentType("text/xml");
            xv.setContentType("text/xml");
            mav.setView(xv);

        } catch (Exception e) {
            e.printStackTrace();
        }

        return mav;
    }

    private void insertMilestone(Element parentElement, Milestone milestone, DatesPojo dates) {

        if (dates.getFirstDate().getTime() > milestone.getBeginDate().getTime()) {
            dates.setFirstDate(milestone.getBeginDate());
        }

        if (dates.getLastDate().getTime() < milestone.getEndDate().getTime()) {
            dates.setLastDate(milestone.getEndDate());
        }
        Tracer progress = delegate.findTracer(milestone.getProject(), Tracer.Type.PROGRESS);
        MilestoneTracer milestoneTracer = delegate.findMilestoneTracer(milestone, progress);
        Double real = milestoneTracer.getRealValue() == null ? 0 : milestoneTracer.getRealValue();

        List<Element> milestoneElement = this.getElement(parentElement, milestone.getIdTask(),
                milestone.getName(), milestone.getBeginDate(),
                DatesUtil.getDifference(milestone.getEndDate(), milestone.getBeginDate(), DatesUtil.WORKING_HOURS),
                real, null);
    }

    private void insertLabel(Element parentElement, Label label, DatesPojo dates) {
        List<Task> tasks = delegate.findTask(label);

        List<Element> labelChilds = this.getElement(parentElement, label.getIdTask(),
                label.getName(), null, null, null, null);

        DatesPojo newDates = new DatesPojo();
        this.insertTasks(labelChilds.get(1), tasks, newDates);

        Double progress = ScoreCardUtils.getRealProgress(delegate, label.getProject(),
                delegate.findTracer(label.getProject(), Tracer.Type.PROGRESS));

        this.addAdvances(labelChilds.get(0), newDates.getFirstDate(), DatesUtil.getDifference(newDates.getLastDate(), newDates.getFirstDate(), DatesUtil.WORKING_HOURS), progress);

        if (dates.getFirstDate().getTime() > newDates.getFirstDate().getTime()) {
            dates.setFirstDate(newDates.getFirstDate());
        }

        if (dates.getLastDate().getTime() < newDates.getLastDate().getTime()) {
            dates.setLastDate(newDates.getLastDate());
        }

    }

    private void insertTasks(Element parentElement, List<? extends Task> tasks, DatesPojo dates) {
        dates.setFirstDate(new Date(Long.MAX_VALUE));
        dates.setLastDate(new Date(Long.MIN_VALUE));

        for (Task task : tasks) {
            this.insertTask(parentElement, task, dates);
        }
    }

    private void insertTask(Element parentElement, Task task, DatesPojo dates) {

        if (task instanceof Label) {
            this.insertLabel(parentElement, (Label) task, dates);
        } else if (task instanceof Milestone) {
            this.insertMilestone(parentElement, (Milestone) task, dates);
        }
    }

    /*
    @return Element: the element in wichr the child elements will be store.
     */
    private List<Element> getElement(Element parentElement, Long id, String name, Date est, Integer duration, Double percentComplete, Integer predecessortasks) {
        List<Element> elements = new ArrayList<Element>();
        Element element = parentElement.addElement("task");
        elements.add(element);
        element.addAttribute("id", id.toString());//.addText(id.toString());
        element.addElement("name").addText(removeLatinChars(name));

        if (est != null) {
            element.addElement("est").addText(sdf.format(est));
        }
        if (duration != null) {
            element.addElement("duration").addText(duration.toString());
        }
        if (percentComplete != null) {
            Long pc = Math.round(percentComplete * 100);
            element.addElement("percentcompleted").addText(pc.toString());
        }
        if (predecessortasks != null) {
            element.addElement("predecessortasks");
        }
        element.addElement("predecessortasks");
        elements.add(element.addElement("childtasks"));

        return elements;
    }

    private void addAdvances(Element element, Date est, Integer duration, Double percentCompleate) {

        element.addElement("est").addText(sdf.format(est));
        element.addElement("duration").addText(duration.toString());

        Long pc = Math.round(percentCompleate * 100);
        element.addElement("percentcompleted").addText(pc.toString());
    }

    private DatesPojo getDates(DelegateBSC delegate, Project project) {
        DatesPojo dates = new DatesPojo();
        List<Milestone> milestones = delegate.findMilestone(project);
        for (Milestone milestone : milestones) {
            if (dates.getFirstDate() == null) {
                dates.setFirstDate(milestone.getBeginDate());
            }
            if (dates.getLastDate() == null) {
                dates.setLastDate(milestone.getEndDate());
            }

            if (milestone.getBeginDate().before(dates.getFirstDate())) {
                dates.setFirstDate(milestone.getBeginDate());
            }
            if (milestone.getEndDate().after(dates.getLastDate())) {
                dates.setLastDate(milestone.getEndDate());
            }
        }
        return dates;
    }

    public static String removeLatinChars(String text){
        for(int i = 0; i < LATIN_CHARS.length; i++) {
            String _char = LATIN_CHARS[i];
            if(text.contains(_char)) text = text.replaceAll(_char, NON_LATIN_CHARS[i]);
        }
        return text.trim();
    }

    public static final String[] LATIN_CHARS= {"á","é","í","ó","ú","ñ","Á","É","Í","Ó","Ú","Ñ"};
    public static final String[] NON_LATIN_CHARS= {"&aacute;","&eacute;","&iacute;","&oacute;","&uacute;","&ntilde;","&Aacute;","&Eacute;","&Iacute;","&Oacute;","&Uacute;","&Ntilde;"};
}